#lang rosetta-racket


(require "lego.rkt")

(provide lego-sphere-example)


(define 2x1x1 (make-xyz-brick 2 1 1))
(define 3x1x1 (make-xyz-brick 3 1 1))
(define 4x1x1 (make-xyz-brick 4 1 1))
(define 6x1x1 (make-xyz-brick 6 1 1))

(define 1x2x1 (make-xyz-brick 1 2 1))
(define 2x2x1 (make-xyz-brick 2 2 1))
(define 4x2x1 (make-xyz-brick 4 2 1))
(define 8x2x1 (make-xyz-brick 8 2 1))

(define 1x3x1 (make-xyz-brick 1 3 1))

(define 1x4x1 (make-xyz-brick 1 4 1))
(define 2x4x1 (make-xyz-brick 2 4 1))

(define 2x8x1 (make-xyz-brick 2 8 1))


(define (put-sphere-brick world brick x y z)
  (put-brick world brick (xyz x y z)))

(define (put-sphere-bricks fn world)
  (let ((size ((world-size world))))
    (define (put-sphere-bricks-rec world i j k)
      (if (>= k (xyz-z size))
          world
          (if (>= j (xyz-y size))
              (put-sphere-bricks-rec world 0 0 (+ k 1))
              (if (>= i (xyz-x size))
                  (put-sphere-bricks-rec world 0 (+ j 1) k)
                  (if (fn world i j k)
                      (let ((world (put-sphere-brick world 1x1x1 i j k)))
                        (put-sphere-bricks-rec world (+ i 1) j k))
                      (put-sphere-bricks-rec world (+ i 1) j k))))))
    (put-sphere-bricks-rec world 0 0 0)))

(define (world-center world)
  (+c ((world-cs world)) (midcoord u0 ((world-size world)))))

(define (sphere-fn d world i j k)
  (< (distance (world-center world) (xyz i j k)) d))

(define (lego-sphere radius size)
  (let ((world (make-voxel-world size)))
    (world-shapes (put-sphere-bricks (cλ sphere-fn radius) world))))

(define (lego-sphere-example)
  (view
   (xyz 91.49932181280005 -17.312161203428317 70.73887829471765)
   (xyz 29.791216224298704 50.77110278641696 46.26332891752698)
   (perspective 30)
   (lego-sphere 4 (xyz 9 9 9))))